package com.starview.star.compiler.wff;

import com.starview.platform.data.IArray;
import com.starview.platform.data.type.Location;
import com.starview.star.compiler.ast.Apply;
import com.starview.star.compiler.ast.IAbstract;
import com.starview.star.compiler.util.PrettyPrintDisplay;

@SuppressWarnings("serial")
public class WffApplyPtn implements WffOp
{
  private final WffOp opOp;
  private final WffOp argOps[];

  public WffApplyPtn(WffOp opOp, WffOp argOps[])
  {
    this.opOp = opOp;
    this.argOps = argOps;
  }

  @Override
  public applyMode apply(IAbstract term, IAbstract env[], Location loc, WffEngine engine)
  {
    if (term instanceof Apply) {
      Apply apply = (Apply) term;

      applyMode mode = opOp.apply(apply.getOperator(), env, loc, engine);

      if (apply.getArgs().size() != argOps.length) {
        mode = applyMode.notValidates;
      }

      if (mode == applyMode.validates) {
        IArray args = apply.getArgs();
        for (int ix = 0; ix < argOps.length && mode == applyMode.validates; ix++)
          mode = argOps[ix].apply((IAbstract) args.getCell(ix), env, loc, engine);
      }
      return mode;
    } else
      return applyMode.notValidates;
  }

  @Override
  public void prettyPrint(PrettyPrintDisplay disp)
  {
    opOp.prettyPrint(disp);
    disp.append("(");
    disp.prettyPrint(argOps, ", ");
    disp.append(")");
  }

  @Override
  public String toString()
  {
    return PrettyPrintDisplay.toString(this);
  }

  @Override
  public long specificity()
  {
    long count = opOp.specificity();
    for (int ix = 0; ix < argOps.length; ix++)
      count += argOps[ix].specificity();
    return count;
  }
}
